using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;
using Volo.Abp.Logging;
using Matrix.Configuration.Providers;
using Matrix.Configuration.DTOs;

namespace Matrix.Configuration.Services
{
    /// <summary>
    /// Matrix配置集成服务
    /// 提供与ABP Configuration系统的深度集成
    /// </summary>
    public class MatrixConfigurationIntegrationService : ITransientDependency
    {
        private readonly IConfiguration _configuration;
        private readonly IConfigurationAppService _configurationAppService;
        private readonly MatrixConfigurationProvider _matrixProvider;
        private readonly IOptionsMonitorCache<object> _optionsCache;
        private readonly ILogger<MatrixConfigurationIntegrationService> _logger;

        public MatrixConfigurationIntegrationService(
            IConfiguration configuration,
            IConfigurationAppService configurationAppService,
            MatrixConfigurationProvider matrixProvider,
            IOptionsMonitorCache<object> optionsCache,
            ILogger<MatrixConfigurationIntegrationService> logger)
        {
            _configuration = configuration;
            _configurationAppService = configurationAppService;
            _matrixProvider = matrixProvider;
            _optionsCache = optionsCache;
            _logger = logger;
        }

        /// <summary>
        /// 初始化集成服务
        /// </summary>
        public async Task InitializeAsync()
        {
            // 加载初始配置
            await _matrixProvider.LoadAsync();

            // 设置配置变更监听
            await SetupConfigurationWatchersAsync();
        }

        /// <summary>
        /// 将Matrix配置同步到IConfiguration
        /// </summary>
        public async Task SyncToIConfigurationAsync(string? @namespace = null)
        {
            try
            {
                var input = new GetConfigurationItemListInput
                {
                    MaxResultCount = 10000
                };

                if (!string.IsNullOrEmpty(@namespace))
                {
                    input.Namespace = @namespace;
                }

                var configs = await _configurationAppService.GetListAsync(input);

                foreach (var config in configs.Items)
                {
                    var key = $"{config.Namespace}:{config.Key}";
                    _matrixProvider.AddOrUpdate(config.Namespace, config.Key, config.Value);
                }

                // 清除选项缓存以触发重新加载
                _optionsCache.Clear();
            }
            catch (Exception ex)
            {
                throw new AbpException("同步Matrix配置到IConfiguration失败", ex);
            }
        }

        /// <summary>
        /// 从IConfiguration同步到Matrix配置
        /// </summary>
        public async Task SyncFromIConfigurationAsync(string? @namespace = null)
        {
            try
            {
                var configs = await _configurationAppService.GetListAsync(new GetConfigurationItemListInput
                {
                    Namespace = @namespace,
                    MaxResultCount = 10000
                });

                foreach (var config in configs.Items)
                {
                    var key = $"{config.Namespace}:{config.Key}";
                    var value = _configuration[key];

                    if (value != null && value != config.Value)
                    {
                        // 更新Matrix配置
                        var updateDto = new UpdateConfigurationItemDto
                        {
                            Value = value,
                            DataType = config.DataType,
                            Description = config.Description
                        };

                        await _configurationAppService.UpdateAsync(config.Id, updateDto);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new AbpException("从IConfiguration同步到Matrix配置失败", ex);
            }
        }

        /// <summary>
        /// 获取类型化配置选项
        /// </summary>
        public T GetOptions<T>(string sectionName) where T : class, new()
        {
            var section = _configuration.GetSection(sectionName);
            var options = new T();
            section.Bind(options);
            return options;
        }

        /// <summary>
        /// 异步获取类型化配置选项
        /// </summary>
        public async Task<T> GetOptionsAsync<T>(string sectionName) where T : class, new()
        {
            // 首先尝试从IConfiguration获取
            var section = _configuration.GetSection(sectionName);
            var options = new T();
            section.Bind(options);

            // 然后尝试从Matrix配置获取并覆盖
            try
            {
                var namespaceConfig = await _configurationAppService.GetByNamespaceAsync(sectionName);
                foreach (var config in namespaceConfig.Items)
                {
                    var property = typeof(T).GetProperty(config.Key);
                    if (property != null && config.Value != null)
                    {
                        try
                        {
                            var convertedValue = Convert.ChangeType(config.Value, property.PropertyType);
                            property.SetValue(options, convertedValue);
                        }
                        catch
                        {
                            // 转换失败时忽略该配置项
                        }
                    }
                }
            }
            catch
            {
                // Matrix配置获取失败时使用IConfiguration的值
            }

            return options;
        }

        /// <summary>
        /// 设置类型化配置选项
        /// </summary>
        public async Task SetOptionsAsync<T>(string sectionName, T options) where T : class
        {
            try
            {
                var properties = typeof(T).GetProperties();
                foreach (var property in properties)
                {
                    var value = property.GetValue(options);
                    if (value != null)
                    {
                        var stringValue = value.ToString() ?? string.Empty;
                        var dataType = property.PropertyType.Name.ToLowerInvariant();

                        var createDto = new CreateConfigurationItemDto
                        {
                            Namespace = sectionName,
                            Key = property.Name,
                            Value = stringValue,
                            DataType = dataType,
                            Description = $"配置选项 {property.Name}"
                        };

                        try
                        {
                            await _configurationAppService.CreateAsync(createDto);
                        }
                        catch (AbpException)
                        {
                            // 配置已存在，更新配置
                            var updateDto = new UpdateConfigurationItemDto
                            {
                                Value = stringValue,
                                DataType = dataType,
                                Description = $"配置选项 {property.Name}"
                            };

                            var existingConfig = await _configurationAppService.GetByKeyAsync(new GetConfigurationItemInput
                            {
                                Namespace = sectionName,
                                Key = property.Name
                            });

                            await _configurationAppService.UpdateAsync(existingConfig.Id, updateDto);
                        }
                    }
                }

                // 同步到IConfiguration
                await SyncToIConfigurationAsync(sectionName);
            }
            catch (Exception ex)
            {
                throw new AbpException($"设置配置选项 {sectionName} 失败", ex);
            }
        }

        /// <summary>
        /// 监听配置选项变更
        /// </summary>
        public void OnOptionsChanged<T>(string sectionName, Action<T, T> onChanged) where T : class, new()
        {
            // 简化实现，实际项目中可以使用IOptionsMonitor<T>
            ChangeToken.OnChange(
                () => _configuration.GetReloadToken(),
                () =>
                {
                    var oldOptions = new T();
                    var newOptions = GetOptions<T>(sectionName);
                    onChanged(oldOptions, newOptions);
                });
        }

        /// <summary>
        /// 设置配置变更监听
        /// </summary>
        private async Task SetupConfigurationWatchersAsync()
        {
            try
            {
                // 监听所有命名空间的配置变更
                var watchId = await _configurationAppService.WatchAsync(
                    new GetConfigurationItemInput { Namespace = "*", Key = "*" },
                    async (configDto) =>
                    {
                        // 配置变更时同步到IConfiguration
                        _matrixProvider.AddOrUpdate(configDto.Namespace, configDto.Key, configDto.Value);

                        // 清除选项缓存
                        _optionsCache.Clear();
                    });

                // 存储watchId以便后续取消监听（如果需要）
            }
            catch (Exception ex)
            {
                // 监听设置失败不应影响主流程
                _logger.LogWarning(ex, "设置配置变更监听失败");
            }
        }
    }
}